package com.chucang.shucang.usr.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.CommonConstant;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.usr.constant.UsrCommonConstant;
import com.chucang.shucang.usr.dao.UserCollectionHoldDao;
import com.chucang.shucang.usr.dto.UserCollectionHoldDTO;
import com.chucang.shucang.usr.entity.UserCollectionHoldEntity;
import com.chucang.shucang.usr.feign.PmsService;
import com.chucang.shucang.usr.feign.vo.CollectionBaseEntity;
import com.chucang.shucang.usr.service.UserCollectionHoldService;
import com.chucang.shucang.usr.service.UserWalletService;
import com.chucang.shucang.usr.vo.UserCollectionHoldResVO;
import com.chucang.shucang.usr.vo.UserCollectionOnConsignVO;
import com.chucang.shucang.usr.vo.UserCollectionSerialNumResVO;
import com.chucang.shucang.usr.vo.UserCollectionSerialNumVO;
import com.chucang.shucang.usr.vo.query.UserCollectionHoldQuery;
import com.github.yitter.idgen.YitIdHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;


/**
 * 用户持有藏品信息表
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Service
@RequiredArgsConstructor
public class UserCollectionHoldServiceImpl extends CrudServiceImpl<UserCollectionHoldDao, UserCollectionHoldEntity, UserCollectionHoldDTO> implements UserCollectionHoldService {

    private final PmsService pmsService;

    private final ThreadPoolTaskExecutor usrExecutor;

    @Override
    public PageData<UserCollectionHoldResVO> userCollectionPage(UserCollectionHoldQuery userCollectionHoldQuery) {

        LambdaQueryWrapper<UserCollectionHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCollectionHoldEntity::getUserId, userCollectionHoldQuery.getId())
                .eq(UserCollectionHoldEntity::getStatus, UsrCommonConstant.COLLECTION_HOLD)
                .select(UserCollectionHoldEntity::getCollectionId);

        IPage<UserCollectionHoldEntity> page = this.page(
                new PageQuery<UserCollectionHoldEntity>().getPage(userCollectionHoldQuery),
                lambdaQueryWrapper
        );
        if (CollUtil.isEmpty(page.getRecords())) {
            return new PageData<>(Collections.emptyList(), 0);
        }
        List<UserCollectionHoldResVO> userCollectionHoldResVOList = new ArrayList<>(32);
        //分类
        page.getRecords()
                .stream()
                .collect(Collectors.groupingBy(UserCollectionHoldEntity::getCollectionId))
                .forEach((k, v) -> {
                    UserCollectionHoldResVO collectionHoldResVO = new UserCollectionHoldResVO();
                    collectionHoldResVO.setId(k);
                    collectionHoldResVO.setHoldNum(v.size());
                    userCollectionHoldResVOList.add(collectionHoldResVO);
                });
        Map<Long, String> hashMap = new HashMap<>(32);
        Map<Long, String> coverPicHashMap = new HashMap<>(32);
        userCollectionHoldResVOList
                .stream()
                .map(c -> CompletableFuture.supplyAsync(() -> {
                                    R<CollectionBaseEntity> baseInfo = pmsService.getCollectionBaseInfo(c.getId(), SecurityConstant.FROM_IN);
                                    return OpsUtil.of(baseInfo)
                                            .assertDataNotNull(e -> new FastException("藏品发售信息为空！"))
                                            .getData()
                                            .get();
                                }, usrExecutor
                        )
                )
                .collect(Collectors.toList())
                .stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList())
                .forEach(d -> {
                    hashMap.put(d.getId(), d.getDcName());
                    coverPicHashMap.put(d.getId(), d.getCoverPicture());
                });
        userCollectionHoldResVOList.forEach(uc -> {
            if (hashMap.containsKey(uc.getId())) {
                uc.setDcName(hashMap.get(uc.getId()));
            }
            if (coverPicHashMap.containsKey(uc.getId())) {
                uc.setCoverPicture(coverPicHashMap.get(uc.getId()));
            }
        });
        return new PageData<>(userCollectionHoldResVOList, page.getTotal());
    }

    @Override
    public List<UserCollectionSerialNumResVO> collectionSerialNumList(UserCollectionSerialNumVO userCollectionSerialNumVO) {
        LambdaQueryWrapper<UserCollectionHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserCollectionHoldEntity::getUserId, userCollectionSerialNumVO.getUserId())
                .eq(UserCollectionHoldEntity::getCollectionId, userCollectionSerialNumVO.getCollectionId())
                .eq(UserCollectionHoldEntity::getStatus, UsrCommonConstant.COLLECTION_HOLD)
                .select(UserCollectionHoldEntity::getSerialNum, UserCollectionHoldEntity::getPurchasePrice);
        List<UserCollectionHoldEntity> list = this.list(lambdaQueryWrapper);
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }

        R<CollectionBaseEntity> collectionBaseInfo = pmsService.getCollectionBaseInfo(userCollectionSerialNumVO.getCollectionId(), SecurityConstant.FROM_IN);
        CollectionBaseEntity baseEntity = OpsUtil.of(collectionBaseInfo)
                .assertDataNotNull(e -> new FastException("藏品信息不能为空"))
                .getData()
                .get();
        return list
                .stream()
                .map(c -> {
                    UserCollectionSerialNumResVO serialNumResVO = new UserCollectionSerialNumResVO();
                    serialNumResVO.setSerialNum(c.getSerialNum());
                    serialNumResVO.setCollectionSerialNum(String.format(UsrCommonConstant.SERIAL_NUM, c.getSerialNum(), baseEntity.getTotalNum()));
                    serialNumResVO.setId(baseEntity.getId());
                    serialNumResVO.setPurchasePrice(c.getPurchasePrice());
                    return serialNumResVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean collectionsOnConsign(UserCollectionOnConsignVO userCollectionOnConsignVO) {
        //查询藏品状态
        LambdaQueryWrapper<UserCollectionHoldEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(UserCollectionHoldEntity::getUserId, userCollectionOnConsignVO.getUserId())
                .eq(UserCollectionHoldEntity::getCollectionId, userCollectionOnConsignVO.getCollectionId())
                .eq(UserCollectionHoldEntity::getStatus, UsrCommonConstant.COLLECTION_HOLD)
                .in(UserCollectionHoldEntity::getSerialNum, userCollectionOnConsignVO.getSerialNums())
                .select();
        List<UserCollectionHoldEntity> list = this.list(lambdaQueryWrapper);
        if (CollUtil.isEmpty(list) || list.size() < userCollectionOnConsignVO.getSerialNums().size()) {
            return false;
        }
        list.forEach(c -> {
            if (Objects.isNull(c.getConsignId())) {
                c.setConsignId(YitIdHelper.nextId());
            }
            c.setStatus(UsrCommonConstant.COLLECTION_CONSIGN);
            c.setSellingPrice(new BigDecimal(userCollectionOnConsignVO.getUnitPrice()));
        });
        //上架商城
        R<String> onConsign = pmsService.collectionsOnConsign(list, SecurityConstant.FROM_IN);
        OpsUtil.of(onConsign).assertCode(CommonConstant.SUCCESS, e -> new FastException("藏品上架商城失败"));
        //商品寄售
        return this.updateBatchById(list);
    }
}